<template>
    <el-upload
        class="up-el"
        v-bind="$attrs"
        v-on="$listeners"
        :accept="accept"
        :action="fileAction"
        :limit="limit"
        :file-list="fileShowList"
        :before-upload="beforeUpload"
        :on-exceed="onExceed"
        :on-success="onSuccess"
        :on-error="onError"
        :on-remove="onRemove"
    >
        <el-button size="small" type="primary">点击上传</el-button>
        <div slot="tip" class="el-upload__tip">{{acceptShow}}</div>
    </el-upload>
</template>
<script lang="ts">
import {
    Component,
    Vue,
    Model,
    Emit,
    Prop,
    Watch
} from "vue-property-decorator";
import { isEmpty, concat } from "lodash";
import { debounce } from "@/utils/Annotate";
import message from "@/utils/Message";
@Component({
    name: "ZbUpload"
})
export default class ZbUpload extends Vue {
    // v-model绑定值
    @Model("change", { type: String }) value!: String;
    @Emit("change") setValue() {}
    // 监听v-model绑定值
    @Watch("value", { immediate: true })
    updateValue(v: string) {
        const me = this as any;
        // 通过标识判断是否是通过value来处理显示值
        if (me.isUp) {
            me.isUp = false;
        } else {
            let list: any = [];
            if (!isEmpty(v)) {
                list = v.split(",");
            }
            const fileShowList: any = [];
            // 遍历值填充数据
            list.forEach((item: any) => {
                fileShowList.push({ name: me.getName(item), url: item });
            });
            // 设置用于显示的列表
            me.fileShowList = fileShowList;
            // 设置文件列表
            me.fileList = list;
        }
    }
    // 允许上传类型
    @Prop({
        default: function () {
            return ["pdf", "img"];
        }
    })
    acceptType!: Array<string>;
    @Watch("acceptType", { immediate: true }) updateAcceptType(
        v: Array<string>
    ) {
        if (!isEmpty(v)) {
            // 根据允许上传类型确定校验规则文案
            const me = this as any;
            let accept: any = [],
                checkList: any = [];
            v.forEach((item: string) => {
                // 上传可选类型
                accept = concat(accept, me[`${item}TypeList`]);
                // 可选类型校验规则
                checkList = concat(checkList, me[`${item}CheckList`]);
            });
            accept = accept.toString();
            // 设置可选类型
            me.accept = accept.toString();
            // 设置校验规则
            me.acceptCheckList = checkList;
            // 设置提示文案
            me.acceptShow = `只能上传${accept
                .replace(/\./g, "")
                .replace(/\,/g, "、")}格式文件`;
        }
    }
    // 上传地址
    @Prop({
        default: `${process.env.VUE_APP_FILEURL}upload?project=loan&code=file`
    })
    fileAction!: any;
    // 文件路径前缀
    @Prop({
        default: process.env.VUE_APP_SHOWURL
    })
    showUrl!: any;

    // 最大允许上传文件数量
    @Prop({ default: 10 })
    limit!: any;

    // 图片类型支持上传格式
    imgTypeList: Array<string> = [".jpg", ".jpeg", ".png"];
    // 图片类型文件校验校验规则
    imgCheckList: Array<string> = ["image/jpeg", "image/jpg", "image/png"];
    // pdf类型支持上传格式
    pdfTypeList: Array<string> = [".pdf"];
    // pdf类型文件校验校验规则
    pdfCheckList: Array<string> = ["application/pdf"];
    // 允许上传类型
    accept: string = "";
    // 运行上传类型校验规则
    acceptCheckList: Array<string> = [];
    // 允许上传类型文案
    acceptShow: string = "";
    // 用于显示的列表
    fileShowList: Array<any> = [];
    // 文件列表
    fileList: Array<any> = [];
    // 是否正在设置数据
    isUp: boolean = false;
    @Watch("fileList")
    updateFileList(v: Array<string>) {
        const me = this as any;
        // 标识当前正在设置数据
        me.isUp = true;
        me.setValue(v.toString());
    }
    // 上传文件之前进行文件格式校验
    beforeUpload(file: any) {
        const me = this as any,
            isJPG = me.acceptCheckList.includes(file.type);
        if (!isJPG) {
            me.showMessage(me.acceptShow, "error");
        } else {
            message.loading("正在上传请等待...");
        }
        return isJPG;
    }
    // 文件上传数量超过限制时
    onExceed(files: any, fileList: any) {
        const me = this as any;
        me.showMessage(
            `当前限制选择 ${me.limit} 个文件，本次选择了 ${
                files.length
            } 个文件，共选择了 ${files.length + fileList.length} 个文件`,
            "warning"
        );
    }
    // 文件上传成功
    onSuccess(url: string) {
        this.fileList.push(`${url[0]}`);
        message.clear();
    }
    // 文件上传失败
    onError() {
        message.clear();
    }
    // 删除文件时
    onRemove(file: any) {
        const fileList = this.fileList,
            // 获取删除文件路径，如果是编辑状态通过file.url获取
            url = file.url || file.response[0];
        this.fileList = fileList.filter((item) => {
            return item.indexOf(url) == -1;
        });
    }
    // 显示消息提升，这里做防抖处理
    @debounce(100)
    showMessage(message: any, type: any) {
        const me = this as any;
        me.$message({
            message: message,
            type: type,
            customClass: "zZindex"
        });
    }

    getName(url: string) {
        return url.replace(/(.*\/)*([^.]+)/i, "$2");
    }
}
</script>
<style scoped lang='scss'>
.up-el {
    width: 100%;
}
.display {
    display: none;
}
</style>
